﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

using SUMO.MediaBrowser.Foundation;
using SUMO.MediaBrowser.ViewModel;
using SUMO.MediaBrowser.Controls.Adorners;
using SUMO.MediaBrowser.Controls.Adorners.Frames;
using UTSF.Media.ImageManipulation;

namespace SUMO.MediaBrowser.Controls.Umbraco {
    public partial class ImageEditor : ChildWindow, IMediaItemEditor
    {
        private Adorner _adorner = null;
        CropFrame _cropFrame = new CropFrame();
        AnimatedRectangleFrame _selectFrame = new AnimatedRectangleFrame();

        public ImageEditor()
        {
            InitializeComponent();
			
			_adorner = new Adorner();
            _adorner.Width = 0;
            _adorner.Height = 0;
            cursorPlane.SetSystemCursorElement(EditorPane);
            _adorner.SetCursor(cursorPlane);
            _adorner.CanRotate = false;
            EditorPane.Children.Add(_adorner);

        }

        public ImageEditor(EditingHierarchicalMediaItem dataItem)
            : this()
        {
            DataContext = dataItem;
			System.IO.MemoryStream m = new System.IO.MemoryStream(dataItem.WorkingData);
			WriteableBitmap bmp = new WriteableBitmap(0, 0);
			bmp.SetSource(m);
			
			EditorImage.Source = bmp;
			EditorImage.Width = bmp.PixelWidth;
			EditorImage.Height = bmp.PixelHeight;
        }

        public EditingHierarchicalMediaItem DataItem
        {
            get
            {
                return DataContext as EditingHierarchicalMediaItem;
            }
            set
            {
                DataContext = value;
            }
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            if (_currentOpStyle == OpStyle.Crop)
            {
                WriteableBitmap b = Manipulator.CropImage(GetEditableBitmapFromCanvas(),(int)_adorner.X, (int)_adorner.Y, (int)_adorner.ActualWidth, (int)_adorner.ActualHeight);
                UpdateImageOnCanvas(b);
            }

            this.DialogResult = true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

        private void RotateButton_Click(object sender, RoutedEventArgs e)
        {
            //TODO: If we are going to handle multiple transitions here, we should really set the view to
            //      the WritableBitmap we are re-rendering, and then do a final Jpeg/Image save when the user
            //      is happy, but there are some considerations when doing this that make it a little more than
            //      trivial. We would then, do this saving to jpeg byte[] data on 'OK'.

            WriteableBitmap b = Manipulator.RotateImage90Degrees(GetEditableBitmapFromCanvas());
            UpdateImageOnCanvas(b);
        }

        private void FlipHButton_Click(object sender, RoutedEventArgs e)
        {
            WriteableBitmap b = Manipulator.FlipHorizontal(GetEditableBitmapFromCanvas());
            UpdateImageOnCanvas(b);
        }

        private void FlipVButton_Click(object sender, RoutedEventArgs e)
        {
            WriteableBitmap b = Manipulator.FlipVertical(GetEditableBitmapFromCanvas());
            UpdateImageOnCanvas(b);
        }

        private void UpdateImageOnCanvas(WriteableBitmap b)
        {
            //Write the image back to the canvas
            b.Invalidate();
            EditorImage.Source = b;
            DataItem.WorkingData = ImageManipulation.GetBase64Jpg(b);
			
            _adorner.Width = 0;
            _adorner.Height = 0;
            _adorner.SetAdornerFrame(null);
			EditorImage.Width = b.PixelWidth;
            EditorImage.Height = b.PixelHeight;
            EditorPane.Width = b.PixelWidth;
            EditorPane.Height = b.PixelHeight;
            ImageCanvas.Width = b.PixelWidth;
            ImageCanvas.Height = b.PixelHeight;
            _adorner.X = 0;
            _adorner.Y = 0;
            _adorner.SetBounds(0, 0, b.PixelWidth, b.PixelHeight);
        }

        private WriteableBitmap GetEditableBitmapFromCanvas()
        {
            WriteableBitmap b = new WriteableBitmap((int)EditorImage.ActualWidth, (int)EditorImage.ActualHeight);
            b.Render(EditorImage, new TranslateTransform());
            b.Invalidate();

            return b;
        }

        private enum OpStyle
        {
            Select,
            Crop
        }

        private OpStyle _currentOpStyle = OpStyle.Select;

        private void CropTabItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _currentOpStyle = OpStyle.Crop;

            _adorner.CanRotate = false;
            _adorner.Width = EditorImage.ActualWidth / 2;
            _adorner.Height = EditorImage.ActualHeight / 2;
            _adorner.SetBounds(0, 0, EditorImage.ActualWidth, EditorImage.ActualHeight);
            _adorner.X = EditorImage.ActualWidth / 4;
            _adorner.Y = EditorImage.ActualHeight / 4;

            _adorner.SetAdornerFrame(_cropFrame);
        }

        private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Image img = (Image)sender;

            switch (_currentOpStyle)
            {
                case OpStyle.Crop:
                    _adorner.SetAdornedObject((IAdornedObject)img.Tag);
                    _adorner.StartMoveDrag();
                    break;
            }

        }

        private void ViewTabItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _currentOpStyle = OpStyle.Select;
            _adorner.SetAdornerFrame(null);
        }

        #region IMediaItemEditor Members


        public bool? UserCommitResult
        {
            get { return DialogResult; }
        }

        #endregion
    }
}

